﻿using System;
using System.Text;
using System.Collections.Generic;
using System.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace Vds2465Telegrams
{
	[TestClass]
	public class UserDataColl_Test
	{
		[TestMethod]
		[Owner("Frank Eppink")]
		public void Test01_Equals()
		{
			UserDataColl userDataColl = new UserDataColl();

			{
				// completely different type - NOT equal
				object dummyObject = new object();
				Assert.IsFalse(userDataColl.Equals(dummyObject));
			}

			{
				// compare with empty collection -> equal
				UserDataColl userDataColl2Compare = new UserDataColl();
				Assert.IsTrue(userDataColl.Equals(userDataColl2Compare));
			}

			ReportType_Device reportType = new ReportType_Device(false, eReportSubType_Device.General);
			UserData userData01 = new UserData_02_StatusChangeReport2Confirm(0x01, 0x02, 0x03, eAddressExtension_1.Input, reportType);
			bool bRetVal01 = userDataColl.Add(userData01);
			Assert.IsTrue(bRetVal01);

			{
				// compare with empty collection -> not equal
				UserDataColl userDataColl2Compare = new UserDataColl();
				Assert.IsFalse(userDataColl.Equals(userDataColl2Compare));

				// compare with collection that has another element -> not equal
				UserData userData2Compare = new UserData_01_Priority(0x02);
				bool bRetVal = userDataColl2Compare.Add(userData2Compare);
				Assert.IsTrue(bRetVal);
				Assert.IsFalse(userDataColl.Equals(userDataColl2Compare));
			}

			{
				// compare with empty collection -> not equal
				UserDataColl userDataColl2Compare = new UserDataColl();
				Assert.IsFalse(userDataColl.Equals(userDataColl2Compare));

				// compare with collection that has the same element -> equal
				bool bRetVal = userDataColl2Compare.Add(userData01);
				Assert.IsTrue(bRetVal);
				Assert.IsTrue(userDataColl.Equals(userDataColl2Compare));
			}

			UserData userData02 = new UserData_01_Priority(0x78);
			bool bRetVal02 = userDataColl.Add(userData02);
			Assert.IsTrue(bRetVal02);

			{
				// compare with empty collection -> not equal
				UserDataColl userDataColl2Compare = new UserDataColl();
				Assert.IsFalse(userDataColl.Equals(userDataColl2Compare));

				// add in different order

				// compare with collection that has only the second added element -> not equal
				bool bRetVal = userDataColl2Compare.Add(userData02);
				Assert.IsTrue(bRetVal);
				Assert.IsFalse(userDataColl.Equals(userDataColl2Compare));

				bRetVal = userDataColl2Compare.Add(userData01);
				Assert.IsTrue(bRetVal);
				Assert.IsTrue(userDataColl.Equals(userDataColl2Compare));
			}
		}

		[TestMethod]
		[Owner("Frank Eppink")]
		public void Test02_GetHashcode()
		{
			UserDataColl userDataColl = new UserDataColl();
			{
				int hashCode = userDataColl.GetHashCode();
			}

			{
				UserData userData = new UserData_01_Priority(0x78);
				userDataColl.Add(userData);
				int hashCode = userDataColl.GetHashCode();
			}

			{
				ReportType_Device reportType = new ReportType_Device(false, eReportSubType_Device.General);
				UserData userData = new UserData_02_StatusChangeReport2Confirm(0x01, 0x02, 0x03, eAddressExtension_1.Input, reportType);
				userDataColl.Add(userData);
				int hashCode = userDataColl.GetHashCode();
			}

			{
				UserData userData = new UserData_01_Priority(0x88);
				userDataColl.Add(userData);
				int hashCode = userDataColl.GetHashCode();
			}
		}

		[TestMethod]
		[Owner("Frank Eppink")]
		public void Test03_ToString()
		{
			UserDataColl userDataColl = new UserDataColl();
			{
				string stringResult = userDataColl.ToString();
				Assert.IsNotNull(stringResult);
			}

			{
				UserData userData = new UserData_01_Priority(0xee);
				userDataColl.Add(userData);
				string stringResult = userDataColl.ToString();
				Assert.IsNotNull(stringResult);
			}

			{
				UserData userData = new UserData_01_Priority(0x88);
				userDataColl.Add(userData);
				string stringResult = userDataColl.ToString();
				Assert.IsNotNull(stringResult);
			}

			{
				ReportType_State reportType = new ReportType_State(false, eReportSubType_State.InternalArea);
				UserData userData = new UserData_02_StatusChangeReport2Confirm(0x11, 0x12, 0x23, eAddressExtension_1.Disruption, reportType);
				userDataColl.Add(userData);
				string stringResult = userDataColl.ToString();
				Assert.IsNotNull(stringResult);
			}
		}

		[TestMethod]
		[Owner("Frank Eppink")]
		public void Test04_General()
		{
			UserDataColl userDataColl = new UserDataColl();

			// high data type number -> last in sequence
			// TODO user last user data (i.e. highest number) when available
			// UserData userData = new UserData(0xFF);
			// userDataColl.Add(userData);

			UserData_01_Priority userData01Priority = new UserData_01_Priority(0x55);
			userDataColl.Add(userData01Priority);

			Assert.AreEqual(1, userDataColl.Count);

			{
				UserData tmpUserData;
				bool bRetVal = userDataColl.GetByIndex(1000, out tmpUserData);
				Assert.IsFalse(bRetVal);
			}

			{
				UserData tmpUserData;
				bool bRetVal = userDataColl.GetByIndex(0, out tmpUserData);
				Assert.IsTrue(bRetVal);
				Assert.AreEqual(userData01Priority, tmpUserData);
			}

			foreach (UserData userDataSingle in userDataColl)
			{
				Assert.IsNotNull(userDataSingle);
			}
		}

		[TestMethod]
		[Owner("Frank Eppink")]
		public void Test05_AddConstraints_Duplicate()
		{
			UserDataColl userDataColl = new UserDataColl();

			{
				UserData userData = new UserData_01_Priority(0xee);
				bool bRetVal = userDataColl.Add(userData);
				Assert.IsTrue(bRetVal);
			}

			{
				// no duplicate constraint
				// try to add this user data type again
				UserData userData = new UserData_01_Priority(0x00);
				bool bRetVal = userDataColl.Add(userData);
				Assert.IsFalse(bRetVal);
			}			
		}

		[TestMethod]
		[Owner("Frank Eppink")]
		public void Test06_AddConstraints_OnlyOneReportDataType()
		{
			UserDataColl userDataColl = new UserDataColl();

			{
				UserData userData = new UserData_01_Priority(0xee);
				bool bRetVal = userDataColl.Add(userData);
				Assert.IsTrue(bRetVal);
			}
			
			{
				// only one report data type constraint

				// add first report data type
				ReportType_Device reportType01 = new ReportType_Device(false, eReportSubType_Device.General);
				UserData userData01 = new UserData_02_StatusChangeReport2Confirm(0x01, 0x02, 0x03, eAddressExtension_1.Input, reportType01);
				bool bRetVal = userDataColl.Add(userData01);
				Assert.IsTrue(bRetVal);

				// try to add second report data type
				ReportType_State reportType02 = new ReportType_State(false, eReportSubType_State.InternalArea);
				UserData userData02 = new UserData_02_StatusChangeReport2Confirm(0x11, 0x12, 0x23, eAddressExtension_1.Disruption, reportType02);
				bRetVal = userDataColl.Add(userData02);
				Assert.IsFalse(bRetVal);
			}
		}

		[TestMethod]
		[Owner("Frank Eppink")]
		public void Test07_AddConstraints_Length()
		{
			// TODO: implement this unit test when there are enough different UserDataTypes so that the limit is reached...

			//UserDataColl userDataColl = new UserDataColl();

			//{				
			//    int lengthOfThisDataType = UserDataColl_Helper.LengthOfUserDataType(userData);
			//    int nrOfAllowedElements = UserDataColl.MaxLength / lengthOfThisDataType;
			//    for (int index = 0; index < nrOfAllowedElements; index++)
			//    {
			//        // we create a new UserData object with a dummy but always changing dataType number
			//        UserData userData = new UserData(index);
			//        bool bRetVal = userDataColl.Add(userData);
			//        Assert.IsTrue(bRetVal);
			//    }
				
			//    // now add the one element that is too much
			//    bool bRetVal02 = userDataColl.Add(userData);
			//    Assert.IsFalse(bRetVal02);
			//}
		}		
	}
}
